package com.dms.modules.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dms.common.exception.BusinessException;
import com.dms.modules.admin.entity.Admin;
import com.dms.modules.admin.mapper.AdminMapper;
import com.dms.modules.admin.service.AdminService;
import com.dms.modules.merchant.entity.Merchant;
import com.dms.modules.merchant.mapper.MerchantMapper;
import com.dms.modules.system.service.RoleUserService;
import com.dms.modules.user.entity.User;
import com.dms.modules.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService, UserDetailsService {

    private final PasswordEncoder passwordEncoder;
    private final RoleUserService roleUserService;

    @Autowired
    private MerchantMapper merchantMapper;
    
    @Autowired
    private UserMapper userMapper;

    public AdminServiceImpl(PasswordEncoder passwordEncoder, RoleUserService roleUserService) {
        this.passwordEncoder = passwordEncoder;
        this.roleUserService = roleUserService;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Admin admin = getByUsername(username);
        if (admin == null) {
            throw new UsernameNotFoundException("管理员不存在");
        }
        return admin;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Admin createAdmin(Admin admin) {
        // 检查用户名是否已存在
        if (getByUsername(admin.getUsername()) != null) {
            throw new BusinessException("用户名已存在");
        }
        
        // 检查手机号是否已存在
        if (StringUtils.isNotBlank(admin.getPhone())) {
            User existUserByPhone = userMapper.selectOne(new LambdaQueryWrapper<User>()
                    .eq(User::getPhone, admin.getPhone()));
            if (existUserByPhone != null) {
                throw new BusinessException("该手机号已被注册，请使用其他手机号");
            }
        }
        
        // 如果指定了关联的用户ID，则检查并更新用户角色
        if (admin.getUserId() != null) {
            User user = userMapper.selectById(admin.getUserId());
            if (user == null) {
                throw new BusinessException("关联的用户不存在");
            }
            
            // 更新用户角色为管理员
            user.setRoleId(1L); // 1-管理员角色
            userMapper.updateById(user);
        } else {
            // 如果没有指定关联用户，则创建新用户并关联
            User user = new User();
            user.setUsername(admin.getUsername());
            user.setPassword(admin.getPassword()); // 密码会在下面进行加密
            user.setNickname(admin.getNickname());
            user.setAvatar(admin.getAvatar());
            user.setEmail(admin.getEmail());
            user.setPhone(admin.getPhone());
            user.setStatus(1);
            user.setRoleId(1L); // 1-管理员角色
            
            // 加密密码
            user.setPassword(passwordEncoder.encode(user.getPassword()));
            userMapper.insert(user);
            
            // 设置管理员关联的用户ID
            admin.setUserId(user.getId());
        }
        
        // 加密密码
        admin.setPassword(passwordEncoder.encode(admin.getPassword()));
        admin.setStatus(1); // 默认启用状态
        admin.setCreateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        admin.setUpdateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        
        save(admin);
        return admin;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Admin updateAdmin(Admin admin) {
        // 检查管理员是否存在
        Admin existingAdmin = getById(admin.getId());
        if (existingAdmin == null) {
            throw new BusinessException("管理员不存在");
        }
        
        // 如果修改了用户名，检查新用户名是否已存在
        if (!existingAdmin.getUsername().equals(admin.getUsername())) {
            if (getByUsername(admin.getUsername()) != null) {
                throw new BusinessException("用户名已存在");
            }
        }
        
        admin.setUpdateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        updateById(admin);
        return admin;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAdmin(Long adminId) {
        // 检查管理员是否存在
        Admin admin = getById(adminId);
        if (admin == null) {
            throw new BusinessException("管理员不存在");
        }
        
        // 删除管理员角色关联
        roleUserService.deleteRolesByUserIdAndType(adminId, 1); // 1-管理员用户类型
        
        // 软删除管理员
        return removeById(adminId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Admin updateStatus(Long adminId, Integer status) {
        Admin admin = getById(adminId);
        if (admin == null) {
            throw new BusinessException("管理员不存在");
        }
        
        admin.setStatus(status);
        admin.setUpdateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        updateById(admin);
        return admin;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean resetPassword(Long adminId, String newPassword) {
        Admin admin = getById(adminId);
        if (admin == null) {
            throw new BusinessException("管理员不存在");
        }
        
        admin.setPassword(passwordEncoder.encode(newPassword));
        admin.setUpdateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        return updateById(admin);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePassword(Long adminId, String oldPassword, String newPassword) {
        Admin admin = getById(adminId);
        if (admin == null) {
            throw new BusinessException("管理员不存在");
        }
        
        if (!passwordEncoder.matches(oldPassword, admin.getPassword())) {
            throw new BusinessException("原密码错误");
        }
        
        admin.setPassword(passwordEncoder.encode(newPassword));
        admin.setUpdateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        return updateById(admin);
    }

    @Override
    public Admin getAdminInfo(Long adminId) {
        return getById(adminId);
    }

    @Override
    public Admin getAdminByUsername(String username) {
        return getByUsername(username);
    }

    @Override
    public IPage<Admin> getAdminPage(Integer page, Integer size, String keyword) {
        Page<Admin> pageParam = new Page<>(page, size);
        LambdaQueryWrapper<Admin> wrapper = new LambdaQueryWrapper<>();
        
        if (keyword != null && !keyword.trim().isEmpty()) {
            wrapper.like(Admin::getUsername, keyword)
                   .or()
                   .like(Admin::getNickname, keyword);
        }
        
        wrapper.orderByDesc(Admin::getCreateTime);
        return page(pageParam, wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateLoginInfo(Long adminId, String ip) {
        Admin admin = getById(adminId);
        if (admin != null) {
            admin.setUpdateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
            updateById(admin);
        }
    }

    @Override
    public Admin getByUsername(String username) {
        return baseMapper.selectByUsername(username);
    }

    @Override
    public List<Merchant> getMerchantList() {
        return merchantMapper.selectList(new LambdaQueryWrapper<Merchant>()
                .orderByDesc(Merchant::getCreateTime));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMerchantStatus(Long id, Integer status) {
        Merchant merchant = merchantMapper.selectById(id);
        if (merchant != null) {
            merchant.setStatus(status);
            merchantMapper.updateById(merchant);
        }
    }

    @Override
    public List<User> getUserList() {
        return userMapper.selectList(new LambdaQueryWrapper<User>()
                .orderByDesc(User::getCreateTime));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserStatus(Long id, Integer status) {
        User user = userMapper.selectById(id);
        if (user != null) {
            user.setStatus(status);
            userMapper.updateById(user);
        }
    }
} 